package com.xc.utils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xc.annotation.WrapQuery;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

public class ParseWrapper {
    public static <T> QueryWrapper<T> parseWrap(Object sour, Class<T> cla) {
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.setEntityClass(cla);

        Class<?> sourCla = sour.getClass();
        Field[] fields = sourCla.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(WrapQuery.class)) {
                String col = getCol(field);
                Object val = getVal(field, sour);
                comboWrap(wrapper, col, val, field);
            }
        }

        return wrapper;
    }

    private static void comboWrap(QueryWrapper wrapper, String col, Object val, Field field) {
        if (Objects.isNull(val)) {
            return;
        } else if (val instanceof String && !StringUtils.hasText((String) val)) {
            return;
        } else if (val instanceof Object[] && ((Object[]) val).length <= 0) {
            return;
        } else if (val instanceof Collection<?> && CollectionUtils.isEmpty((Collection<?>) val)) {
            return;
        }
        switch (field.getAnnotation(WrapQuery.class).condition()) {
            case EQ:
                wrapper.eq(col, val);
                break;
            case GT:
                wrapper.gt(col, val);
                break;
            case LT:
                wrapper.lt(col, val);
                break;
            case GE:
                wrapper.ge(col, val);
                break;
            case LE:
                wrapper.le(col, val);
                break;
            case IN:
                if (val instanceof Collection<?>) {
                    wrapper.in(col, (Collection<?>) val);
                } else if (val instanceof Object[]) {
                    List<Object> list = Arrays.stream((Object[]) val).toList();
                    wrapper.in(col, list);
                } else {
                    List<Object> list = List.of(val);
                    wrapper.in(col, list);
                }
                break;
            case NOTIN:
                if (val instanceof Collection<?>) {
                    wrapper.notIn(col, (Collection<?>) val);
                } else if (val instanceof Object[]) {
                    List<Object> list = Arrays.stream((Object[]) val).toList();
                    wrapper.notIn(col, list);
                } else {
                    List<Object> list = List.of(val);
                    wrapper.notIn(col, list);
                }
                break;
            case LIKE:
                wrapper.like(col, val);
                break;
            case NOTLIKE:
                wrapper.notLike(col, val);
                break;
            case LIKELEFT:
                wrapper.likeLeft(col, val);
                break;
            case NOTLIKELEFT:
                wrapper.notLikeLeft(col, val);
                break;
            case LIKERIGHT:
                wrapper.likeRight(col, val);
                break;
            case NOTLIKERIGHT:
                wrapper.notLikeRight(col, val);
                break;
        }
/*        // jdk 12+ 可换用下面写法
        switch (field.getAnnotation(WrapQuery.class).condition()) {
            case EQ -> wrapper.eq(col, val);
            case GT -> wrapper.gt(col, val);
            case LT -> wrapper.lt(col, val);
            case GE -> wrapper.ge(col, val);
            case LE -> wrapper.le(col, val);
            case IN -> {
                if (val instanceof Collection<?>) {
                    wrapper.in(col, (Collection<?>) val);
                } else if (val instanceof Object[]) {
                    List<Object> list = Arrays.stream((Object[]) val).toList();
                    wrapper.in(col, list);
                } else {
                    List<Object> list = List.of(val);
                    wrapper.in(col, list);
                }
            }
            case NOTIN -> {
                if (val instanceof Collection<?>) {
                    wrapper.notIn(col, (Collection<?>) val);
                } else if (val instanceof Object[]) {
                    List<Object> list = Arrays.stream((Object[]) val).toList();
                    wrapper.notIn(col, list);
                } else {
                    List<Object> list = List.of(val);
                    wrapper.notIn(col, list);
                }
            }
            case LIKE -> wrapper.like(col, val);
            case NOTLIKE -> wrapper.notLike(col, val);
            case LIKELEFT -> wrapper.likeLeft(col, val);
            case NOTLIKELEFT -> wrapper.notLikeLeft(col, val);
            case LIKERIGHT -> wrapper.likeRight(col, val);
            case NOTLIKERIGHT -> wrapper.notLikeRight(col, val);
        }*/
    }

    private static Object getVal(Field field, Object sour) {
        field.setAccessible(true);
        Object val = null;
        try {
            val = field.get(sour);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return val;

/*        Object val = null;
        try {
            PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), sour.getClass());
            Method readMethod = descriptor.getReadMethod();
            val = readMethod.invoke(sour);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return val;*/
    }

    private static String getCol(Field field) {
        WrapQuery annotation = field.getAnnotation(WrapQuery.class);
        return StringUtils.hasText(annotation.colName()) ? annotation.colName() : field.getName();
    }
}
